package com.jfinal.plugin.radius.attribute;

import com.jfinal.plugin.radius.dictionary.AttributeType;
import com.jfinal.plugin.radius.util.RadiusException;
import com.jfinal.plugin.radius.util.RadiusUtil;

/**
 * This class represents a Radius attribute which only
 * contains a 32 bit integer.
 */
public class IntegerAttribute extends RadiusAttribute {

	/**
	 * Constructs an empty integer attribute.
	 */
	public IntegerAttribute() {
		super();
	}
	
	/**
	 * Constructs an integer attribute with the given value.
	 * @param type attribute type
	 * @param value attribute value
	 */
	public IntegerAttribute(int type, int value) {
		setAttributeType(type);
		setAttributeValue(value);
	}
	
	/**
	 * Returns the string value of this attribute.
	 * @return a string
	 */
	public int getAttributeValueInt() {
		return getAttributeValueInt(getAttributeData());
	}
	
	/**
     * Returns the string value of the given attribute.
     * @param data the attribute data.
     * @return a string
     */
    public static int getAttributeValueInt(byte[] data) {
        /*
        return (((data[0] & 0x0ff) << 24) | ((data[1] & 0x0ff) << 16) | 
                ((data[2] & 0x0ff) << 8) | (data[3] & 0x0ff));
                */
        int r = 0;
        for(byte b : data)
            r = (r << 8) | (b & 0xff);
        return r;
    }

	/**
	 * Returns the value of this attribute as a string.
	 * Tries to resolve enumerations.
	 * @see com.jfinal.plugin.radius.attribute.RadiusAttribute#getAttributeValue()
	 */
	public String getAttributeValue() {
	    return getAttributeValue(getAttributeData(), getAttributeTypeObject());
	}

   /**
     * Returns the value of this attribute as a string.
     * Tries to resolve enumerations.
     * @param data the attribute data.
     * @param at the attribute type.
     * @return the value.
     * @see com.jfinal.plugin.radius.attribute.RadiusAttribute#getAttributeValue()
     */
    public static String getAttributeValue(byte[] data, AttributeType at) {
        int value = getAttributeValueInt(data);
        if (at != null) {
            String name = at.getEnumeration(value);
            if (name != null)
                return name;
        }

        return Integer.toString(value);
    }

	/**
	 * Sets the value of this attribute.
	 * @param value integer value
	 */
	public void setAttributeValue(int value) {
		byte[] data = new byte[4];
		data[0] = (byte)(value >> 24 & 0x0ff);
		data[1] = (byte)(value >> 16 & 0x0ff);
		data[2] = (byte)(value >> 8 & 0x0ff);
		data[3] = (byte)(value & 0x0ff);
		setAttributeData(data);
	}
	
	/**
	 * Sets the value of this attribute.
	 * @exception NumberFormatException if value is not a number and constant cannot be resolved
	 * @see com.jfinal.plugin.radius.attribute.RadiusAttribute#setAttributeValue(java.lang.String)
	 */
	public void setAttributeValue(String value) {
		AttributeType at = getAttributeTypeObject();
		if (at != null) {
			Integer val = at.getEnumeration(value);
			if (val != null) {
				setAttributeValue(val.intValue());
				return;
			}
		}
		
		setAttributeValue(Integer.parseInt(value));
	}
	
	/**
	 * Check attribute length.
	 * @see com.jfinal.plugin.radius.attribute.RadiusAttribute#readAttribute(byte[], int, int)
	 */
	public void readAttribute(byte[] data, int offset, int length)
	throws RadiusException {
		if (length != 6 && length != 4 && length != 3) // int4, int2, int1
			throw new RadiusException("integer attribute: expected 4 bytes data, length="+length
			        +" data="+RadiusUtil.escape(data,offset, Math.min(length, data.length-offset)));
		super.readAttribute(data, offset, length);
	}
	
}
